package server;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import actions.Action;
import actions.Commands;
import actions.server.GetMsj;
import actions.server.MsjsRequestAction;
import actions.server.NoAction;
import actions.server.RegisterAction;
public class Servidor 
	implements Runnable
{
	
	ServerSocket serverSocket;
	
	public final int port;
	
	Map<String,Usuario> usuarios;
	private final String serverName;
	
	private PrintWriter out;
	private BufferedReader in; 
	
	private ColaCircular coladeMensajes;
	
	public Servidor( String _serverName, int _port ) 
	{
		serverName=_serverName;
		usuarios=new HashMap<String, Usuario>();
		port=_port;
		coladeMensajes=new ColaCircular(300);
		
		
	}
	
	public void addUser(String _to)
	{
		usuarios.put(_to, new Usuario(_to));
	}

	void listen() {
		try 
		{
			serverSocket = new ServerSocket( port );
			System.out.println( serverName + ": Escucho el puerto " + port );
			
			
			while (true)
			{
				Socket clientSocket = serverSocket.accept();


				out = new PrintWriter(clientSocket.getOutputStream(), true);
				in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));	
				
				
				System.out.println(serverName + ": Sirvo al cliente " + in.readLine());
				
				String clientInputString = in.readLine();
				
				if (clientInputString.equals("#HALT"))
				{
					System.out.println("Cerrando...");
					break;
				}
				
				
				parseClientInput(clientInputString);
							
				clientSocket.close();
				
			}
			
		} 
		catch( Exception e ) 
		{
			System.out.println( e.getMessage() );
		}
		finally
		{
			try {
				serverSocket.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}


	private void parseClientInput(String _clientInputString) {
		
		if (_clientInputString.charAt(0) == '#')
		{
			_clientInputString=_clientInputString.substring(1);
		}
		else
		{
			System.out.println(_clientInputString+" no tiene comando.");
			return;
		}

		String[] clientInputStrings=_clientInputString.split(" ");
		
		String command = clientInputStrings[0];
		
		String[] args = Arrays.copyOfRange(clientInputStrings, 1, clientInputStrings.length - 1);
		
		Action action=getAction(command, args, in, out, usuarios, coladeMensajes);
		
		String parseResult=action.parseArguments();
		if (!parseResult.equals(Commands.OK))
		{
			System.out.println(parseResult);
			return;
		}
		
		
		action.doAction();
				

	}


	private Action getAction(String command, String[] _arguments, BufferedReader _in, PrintWriter _out, Map<String, Usuario> _usuarios, ColaCircular _colaMensajes) {
		
		if ( command.equals(Commands.REGISTER))
		{
			return new RegisterAction(_arguments, _in, _out, _usuarios, _colaMensajes);			
		}
		
		if ( command.equals(Commands.UNREGISTER))
		{
			return new RegisterAction(_arguments, _in, _out, _usuarios, _colaMensajes);			
		}
		
		if ( command.equals(Commands.GET))
		{
			return new MsjsRequestAction(_arguments, _in, _out, _usuarios, _colaMensajes);
		}
		
		if ( command.equals(Commands.ADD))
		{
			return new GetMsj(_arguments, _in, _out, _usuarios, _colaMensajes);
		}
		
		return new NoAction(_arguments, _in, _out, _usuarios);
		
	}

	@Override
	public void run() {
		new Servidor("LiveChatServer", 5000).listen();
		
	}


}
